
import Foundation
import SQLite

let gosnUser = OsnUser()

class OsnUser {
    var defaultName = "OSPN User"
    var defaultPortrait = ""
    
    func fromJson(_ json:[String:Any], _ user:DMCCUser?) -> DMCCUser {
        let u = DMCCUser()
        u.userId = json["userID"] as? String ?? ""
        u.state = json["state"] as? Int ?? 0
        u.content = json["content"] as? String ?? ""
        u.name = json["name"] as? String ?? ""
        u.alias = json["displayName"] as? String ?? ""
        u.describes = json["describes"] as? String ?? ""
        u.portrait = json["portrait"] as? String ?? ""
        u.role = json["role"] as? String ?? ""
        u.timestamp = json["timestamp"] as? Int64 ?? 0
        
        if(!u.describes.isEmpty) {
            if let describes = OsnUtils.toJson(u.describes) {
                u.nft = describes["nft"] as? String ?? ""
            }
        }
        if(user != nil){
            if(u.name.isEmpty) { u.name = user!.name }
            if(u.role.isEmpty) { u.role = user!.role }
            u.state = user!.state
            //u.friendAlias = user.friendAlias
        }
        return u
    }
    func fetchUserInfo(_ osnId:String) async -> DMCCUser? {
        print("fetchUserInfo: \(osnId)")
        let user = getUserInfo(osnId)
        guard let info = await gimService.imRequest("GetUserInfo", osnId, nil) else {return nil}
        guard let res = gimService.getResult(info) else {return nil}
        print("\(res)")
        let userInfo = fromJson(res, user)
        _ = setUserInfo(userInfo)
        return userInfo
    }
    
    func fetchMyInfo() async -> DMCCUser? {
        let osnId = myId()
        print("fetchUserInfo: \(osnId)")
        let user = getUserInfo(osnId)
        guard let info = await gimService.imRequest("GetUserInfo", osnId, nil) else {return nil}
        guard let res = gimService.getResult(info) else {return nil}
        print("\(res)")
        let userInfo = fromJson(res, user)
        _ = setUserInfo(userInfo)
        return userInfo
    }
    
    func myId()->String{
        return gimService.mOsnId
    }
    
//    class func getUserInfo(_ osnId:String) -> DMCCUser? {
//        var userId = osnId.isEmpty ? gimService.mOsnId : osnId
//        return dbUser.getUserInfo(userId)
//    }
    
    func getUserInfo(_ osnId:String) -> DMCCUser? {
        let userId = osnId.isEmpty ? gimService.mOsnId : osnId
        return dbUser.getUserInfo(userId)
    }
    
    func setUserInfo(_ info:DMCCUser) -> Bool {
        return dbUser.addUserInfo(info)
    }
    func getUserInfoDefault(_ osnId:String) ->DMCCUser {
        if let user = getUserInfo(osnId) {
            user.isNull = false
            return user
        }
        let user = DMCCUser()
        user.userId = osnId
        user.isNull = true
        user.name = defaultName
        user.portrait = defaultPortrait
        Task { await gidService.refreshId(IdsType.user, osnId) }
        return user
    }
    func setDefaultUserInfo(_ name:String, _ portrait:String){
        defaultName = name
        defaultPortrait = portrait
    }
    func modifyUserInfo(_ info:[String:Any]) async -> Bool {
        return await gimService.imRequestServiceWithError("SetUserInfo", info).1 == nil
    }
    func upDescribes(_ data:[String:Any]) async ->Bool {
        return await gimService.imRequestServiceWithError("UpDescribes", data).1 == nil
    }
    func delDescribes(_ data:[String:Any]) async ->Bool {
        return await gimService.imRequestServiceWithError("RemoveDescribes", data).1 == nil
    }
    func upRole(_ data:[String:Any]) async ->Bool {
        return await gimService.imRequestServiceWithError("UpRole", data).1 == nil
    }
    func getUserAddFriendType(_ osnId:String) ->String {
        guard let user = getUserInfo(osnId) else {return ""}
        return user.role
    }
    func setUserAddFriendType(_ role:String) async ->Bool {
        let data:[String:Any] = ["role":["AddFriend": role ]]
        guard await upRole(data) else {return false}
        if let userInfo = getUserInfo(""){
            userInfo.role = role
            return setUserInfo(userInfo)
        }
        return false
    }
    func setPortraitWithUrl(_ url:String) async -> Bool {
        guard await modifyUserInfo([ "portrait": url ]) else {return false}
        if let user = getUserInfo(gimService.mOsnId){
            user.portrait = url
            guard setUserInfo(user) else {return false}
            guard await setNft("") else {return false}
            return true
        }
        return false
    }
    func setAlias(_ alias:String) async -> Bool {
        guard await modifyUserInfo([ "displayName": alias ]) else {return false}
        if let user = getUserInfo(""){
            user.alias = alias
            return setUserInfo(user)
        }
        return false
    }
    private func addDescribes(_ user:DMCCUser, _ key:String, _ value:String){
        var data:[String:Any] = [:]
        if(!user.describes.isEmpty){
            data = OsnUtils.toJson(user.describes) ?? [:]
        }
        data[key] = value
        user.describes = OsnUtils.toString(data) ?? ""
    }
    func setNft(_ url:String) async -> Bool {
        guard await upDescribes(["data": [ "nft": url ]]) else {return false}
        if let user = getUserInfo(""){
            user.nft = url
            addDescribes(user, "nft", url)
            return setUserInfo(user)
        }
        return false
    }
    func setAllowTemporaryChat(_ str:String) async -> Bool {
        guard await upDescribes(["data": [ "AllowTemporaryChat": str ]]) else {return false}
        if let user = getUserInfo(""){
            addDescribes(user, "AllowTemporaryChat", str)
            return setUserInfo(user)
        }
        return false
    }
}


